package com.cjj2016.cjj.mycanvasdemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by CJJ on 2017/3/20.
 */

public class MyView extends View {

    public static final int DRAWMODE_UNKNOW = 0;
    public static final int DRAWMODE_AXIS = 1;
    public static final int DRAWMODE_ARGB= 2;
    public static final int DRAWMODE_TEXT= 3;
    public static final int DRAWMODE_POINT= 4;
    public static final int DRAWMODE_LINE= 5;
    public static final int DRAWMODE_RECT= 6;
    public static final int DRAWMODE_CIRCLE= 7;
    public static final int DRAWMODE_OVAL= 8;
    public static final int DRAWMODE_ARC= 9;
    public static final int DRAWMODE_PATH= 10;
    public static final int DRAWMODE_BITMAP= 11;



    private int mDrawMode=0;

    private float density = getResources().getDisplayMetrics().density;//获取屏幕密度值

    private Paint mPaint;

    private float textSize =40;

    public MyView(Context context) {
        this(context,null);
    }

    public MyView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init();
    }

    private void init(){
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    }




    public void setDrawMode(int drawMode) {
        this.mDrawMode = drawMode;
        postInvalidate();
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        switch (mDrawMode){
            case DRAWMODE_AXIS:
                drawAxis(canvas);
                break;
            case DRAWMODE_ARGB:
                drawARGB(canvas);
                break;
            case DRAWMODE_TEXT:
                drawText(canvas);
                break;
            case DRAWMODE_POINT:
                drawPoint(canvas);
                break;
            case DRAWMODE_LINE:
                drawLine(canvas);
                break;
            case DRAWMODE_RECT:
                drawRect(canvas);
                break;
            case DRAWMODE_CIRCLE:
                drawCircle(canvas);
                break;
            case DRAWMODE_OVAL:
                drawOval(canvas);
                break;
            case DRAWMODE_ARC:
                drawArc(canvas);
                break;
            case DRAWMODE_PATH:
                drawPath(canvas);
                break;
            case DRAWMODE_BITMAP:
                drawBitmap(canvas);
                break;
        }


    }



    //绘制坐标
    private void drawAxis(Canvas canvas) {
        int canvasWidth = canvas.getWidth();
        int canvasHeight = canvas.getHeight();

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth( 6*density );

        //第一次绘制坐标轴
        mPaint.setColor(Color.GREEN);
        canvas.drawLine(0,0,canvasWidth,0,mPaint); //绘制x轴
        mPaint.setColor(Color.BLUE);
        canvas.drawLine(0,0,0,canvasHeight,mPaint); //绘制y轴

        //对坐标系平移后，第二次绘制坐标轴
        canvas.translate(canvasWidth/4,canvasWidth/4);
        mPaint.setColor(Color.GREEN);
        canvas.drawLine(0,0,canvasWidth,0,mPaint); //绘制x轴
        mPaint.setColor(Color.BLUE);
        canvas.drawLine(0,0,0,canvasHeight,mPaint); //绘制y轴


        //再次平移坐标系并在此基础上旋转坐标系，第三次绘制坐标轴
        canvas.translate(canvasWidth/4,canvasWidth/4); //在上次平移的基础上再把坐标系向右下角平移
        canvas.rotate(30);//基于当前绘图坐标系的原点旋转30度
        mPaint.setColor(Color.GREEN);
        canvas.drawLine(0,0,canvasWidth,0,mPaint); //绘制x轴
        mPaint.setColor(Color.BLUE);
        canvas.drawLine(0,0,0,canvasHeight,mPaint); //绘制y轴


    }


    //对整个Canvas以某种统一的颜色整体绘制
    private void drawARGB(Canvas canvas) {
        canvas.drawARGB(255,139,197,186);
    }

    //绘制文字
    private void drawText(Canvas canvas) {
        int halfCanvasWidth = canvas.getWidth()/2;
        mPaint.setTextSize(textSize);
        float textHeight = textSize;
        float translateY=0;

        //绘制正常文字
        translateY = textHeight;
        canvas.save();
        canvas.translate(0,translateY);
        canvas.drawText("正常绘制文字",0,0,mPaint);
        canvas.restore();

        //绘制绿色文字
        translateY += textHeight*2;
        mPaint.setColor(0xFF00FF00); //这是字体颜色为绿色
        canvas.save();
        canvas.translate(0,translateY);
        canvas.drawText("绘制绿色文字",0,0,mPaint);
        canvas.restore();

        //绘制左对齐文字
        translateY += textHeight*2;
        mPaint.setColor(0xff000000);  //重新设置字体颜色为黑色
        mPaint.setTextAlign(Paint.Align.LEFT); //左对齐
        canvas.save();
        canvas.translate(halfCanvasWidth,translateY);
        canvas.drawText("左对齐文字",0,0,mPaint);
        canvas.restore();


        //绘制居中对齐文字
        translateY += textHeight*2;
        mPaint.setTextAlign(Paint.Align.CENTER); //居中
        canvas.save();
        canvas.translate(halfCanvasWidth,translateY);
        canvas.drawText("居中对齐文字",0,0,mPaint);
        canvas.restore();


        //绘制右对齐文字
        translateY += textHeight*2;
        mPaint.setTextAlign(Paint.Align.RIGHT); //右对齐
        canvas.save();
        canvas.translate(halfCanvasWidth,translateY);
        canvas.drawText("右对齐文字",0,0,mPaint);
        canvas.restore();

        //绘制下划线文字
        translateY += textHeight*2;
        mPaint.setTextAlign(Paint.Align.LEFT); //重新设置左对齐
        mPaint.setUnderlineText(true); //设置下划线
        canvas.save();
        canvas.translate(0,translateY);
        canvas.drawText("下划线文字",0,0,mPaint);
        canvas.restore();
        mPaint.setUnderlineText(false);

        //绘制粗体文字
        translateY += textHeight*2;
        mPaint.setFakeBoldText(true);//设置粗体
        canvas.save();
        canvas.translate(0,translateY);
        canvas.drawText("粗体文字",0,0,mPaint);
        canvas.restore();
        mPaint.setFakeBoldText(false);



        //文本绕绘制起点顺时针旋转20度
        translateY += textHeight*2;
        canvas.save();
        canvas.translate(0,translateY);
        canvas.rotate(20); //旋转20度
        canvas.drawText("文本绕绘制起点顺时针旋转20度",0,0,mPaint);
        canvas.restore();


    }



    //画点
    private void drawPoint(Canvas canvas) {
        int canvasWidth = canvas.getWidth();
        int canvasHeight = canvas.getHeight();

        int x = canvasWidth / 2;
        int deltaY = canvasHeight / 3;
        int y = deltaY / 2;

        mPaint.setColor(0xFF8BC5BA);
        mPaint.setStrokeWidth(20*density); //设置线宽，否则无法绘制点

        //绘制Cap为BUTT的点
        mPaint.setStrokeCap(Paint.Cap.BUTT);
        canvas.drawPoint(x,y,mPaint);


        //绘制Cap为ROUND的点
        canvas.translate(0,deltaY);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        canvas.drawPoint(x,y,mPaint);


        //绘制Cap为SQUARE的点
        canvas.translate(0,deltaY);
        mPaint.setStrokeCap(Paint.Cap.SQUARE);
        canvas.drawPoint(x,y,mPaint);


    }


    //画线
    private void drawLine(Canvas canvas) {
        int canvasWidth = canvas.getWidth();
        int canvasHeight = canvas.getHeight();
        int halfWidth = canvasWidth / 2;
        int deltaY = canvasHeight/ 5;
        int halfDeltaY = deltaY / 2;

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(1);

        //画线
        canvas.drawLine(10,10,canvasWidth-50,deltaY/2,mPaint);

        //画折线
        //drawLines方法接收一个float数组pts，需要注意的是在用drawLines绘图时，
        // 其每次从pts数组中取出四个点绘制一条线段，然后再取出后面四个点绘制一条线段，
        // 所以要求pts的长度需要是4的倍数。假设我们有四个点，分别是p1、p2、p3、p4，我们依次将其坐标放到pts数组中，
        // 即pts = {p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y}，那么用drawLines绘制pts时，
        // 你会发现p1和p2之间画了一条线段，p3和p4之间画了一条线段，
        // 但是p2和p3之间没有画线段，这样大家就应该能明白drawLines每次都需要从pts数组中取出4个值绘制一条线段的意思了
        float[] pts = {
                50,10,halfWidth,halfDeltaY,
                halfWidth,halfDeltaY,canvasWidth-50,10
        };
        canvas.save();
        canvas.translate(0,deltaY);
        canvas.drawLines(pts,mPaint);
        canvas.restore();


        //设置线宽
        mPaint.setStrokeWidth( 10*density);

        //画CAP为BUTT的线
        mPaint.setStrokeCap(Paint.Cap.BUTT);
        canvas.save();
        canvas.translate(0,canvasHeight/2);
        canvas.drawLine(50,0,halfWidth,0,mPaint);
        canvas.restore();



        //画CAP为ROUND的线
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        canvas.save();
        canvas.translate(0,canvasHeight/2+50);
        canvas.drawLine(50,0,halfWidth,0,mPaint);
        canvas.restore();


        //画CAP为SQUARE的线
        mPaint.setStrokeCap(Paint.Cap.SQUARE);
        canvas.save();
        canvas.translate(0,canvasHeight/2+100);
        canvas.drawLine(50,0,halfWidth,0,mPaint);
        canvas.restore();


    }


    //画矩形
    private void drawRect(Canvas canvas) {
        int canvasWidth = canvas.getWidth();
        int canvasHeight = canvas.getHeight();

        mPaint.setColor(Color.LTGRAY);
        int left1 = 10;
        int top1 = 10;
        int right1 = canvasWidth/3;
        int bottom1= canvasHeight/3;
        canvas.drawRect(left1,top1,right1,bottom1,mPaint);


        mPaint.setColor(0xff8bc5ba);
        int left2 = canvasWidth/3 * 2;
        int top2 = 10;
        int right2 = canvasWidth - 10;
        int bottom2 = canvasHeight/3;
        canvas.drawRect(left2,top2,right2,bottom2,mPaint);


    }


    //画圆
    private void drawCircle(Canvas canvas) {
        int canvasWidth = canvas.getWidth();
        int canvasHeight = canvas.getHeight();
        int halfCanvasWidth = canvasWidth / 2;
        int D = canvasHeight / 4;
        int R = D / 2;

        //绘制圆
        mPaint.setColor(Color.GREEN);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.translate(0,D/4);
        canvas.drawCircle(halfCanvasWidth,R,R,mPaint);


        //绘制圆环
        mPaint.setColor(0xFF8BC5BA);
        mPaint.setStyle(Paint.Style.STROKE);    //绘图为线条模式
        mPaint.setStrokeWidth(20);
        canvas.translate(0,D+D/4);
        canvas.drawCircle(halfCanvasWidth,R,R,mPaint);

    }


    //画椭圆
    private void drawOval(Canvas canvas) {
        int canvasWidth = canvas.getWidth();
        int canvasHeight = canvas.getHeight();
        float quarter = canvasHeight / 4;
        float left = 10 * density;
        float top = 0;
        float right = canvasWidth - left;
        float bottom= quarter;
        RectF rectF = new RectF(left, top, right, bottom);

        //绘制椭圆形轮廓线
        mPaint.setColor(0xFF8BC5BA);
        mPaint.setStyle(Paint.Style.STROKE); //设置画笔为画线条模式
        mPaint.setStrokeWidth(2*density); //设置线宽
        canvas.translate(0,quarter/4);
        canvas.drawOval(rectF,mPaint);


        //绘制椭圆形填充面
        mPaint.setStyle(Paint.Style.FILL); //设置画笔为填充模式
        canvas.translate(0,quarter+quarter/4);
        canvas.drawOval(rectF,mPaint);

        //画两个椭圆，形成轮廓线和填充色不同的效果
        canvas.translate(0, (quarter + quarter / 4));
        //1. 首先绘制填充色
        mPaint.setStyle(Paint.Style.FILL);//设置画笔为填充模式
        canvas.drawOval(rectF, mPaint);//绘制椭圆形的填充效果
        //2. 将线条颜色设置为蓝色，绘制轮廓线
        mPaint.setStyle(Paint.Style.STROKE);//设置画笔为线条模式
        mPaint.setColor(0xff0000ff);//设置填充色为蓝色
        canvas.drawOval(rectF, mPaint);//设置椭圆的轮廓线



    }




    //画弧
    private void drawArc(Canvas canvas){
        int canvasWidth = canvas.getWidth();
        int canvasHeight = canvas.getHeight();
        int count = 5;
        float ovalHeight = canvasHeight / (count + 1);
        float left = 10 * density;
        float top = 0;
        float right = canvasWidth - left;
        float bottom= ovalHeight;
        RectF rectF = new RectF(left, top, right, bottom);

        mPaint.setStrokeWidth(2 * density);//设置线宽
        mPaint.setColor(0xff8bc5ba);//设置颜色
        mPaint.setStyle(Paint.Style.FILL);//默认设置画笔为填充模式

        //绘制用drawArc绘制完整的椭圆
        canvas.translate(0, ovalHeight / count);
        canvas.drawArc(rectF, 0, 360, true, mPaint);

        //绘制椭圆的四分之一,起点是钟表的3点位置，从3点绘制到6点的位置
        canvas.translate(0, (ovalHeight + ovalHeight / count));
        canvas.drawArc(rectF, 0, 90, true, mPaint);

        //绘制椭圆的四分之一,将useCenter设置为false
        canvas.translate(0, (ovalHeight + ovalHeight / count));
        canvas.drawArc(rectF, 0, 90, false, mPaint);

        //绘制椭圆的四分之一，只绘制轮廓线
        mPaint.setStyle(Paint.Style.STROKE);//设置画笔为线条模式
        canvas.translate(0, (ovalHeight + ovalHeight / count));
        canvas.drawArc(rectF, 0, 90, true, mPaint);

        //绘制带有轮廓线的椭圆的四分之一
        //1. 先绘制椭圆的填充部分
        mPaint.setStyle(Paint.Style.FILL);//设置画笔为填充模式
        canvas.translate(0, (ovalHeight + ovalHeight / count));
        canvas.drawArc(rectF, 0, 90, true, mPaint);
        //2. 再绘制椭圆的轮廓线部分
        mPaint.setStyle(Paint.Style.STROKE);//设置画笔为线条模式
        mPaint.setColor(0xff0000ff);//设置轮廓线条为蓝色
        canvas.drawArc(rectF, 0, 90, true, mPaint);
    }

    //画path
    private void drawPath(Canvas canvas) {
        int canvasWidth = canvas.getWidth();
        int deltaX = canvasWidth / 4;
        int deltaY = (int)(deltaX * 0.75);

        mPaint.setColor(0xff8bc5ba);//设置画笔颜色
        mPaint.setStrokeWidth(4);//设置线宽

        /*--------------------------用Path画填充面-----------------------------*/
        mPaint.setStyle(Paint.Style.FILL);//设置画笔为填充模式
        Path path1 = new Path();
        //向Path中加入Arc
        RectF arcRectf = new RectF(0,0,deltaX,deltaY);
        path1.addArc(arcRectf,0,135);
        //向Path中添加Oval
        RectF ovalRectf = new RectF(deltaX,0,deltaX*2,deltaY);
        path1.addOval(ovalRectf, Path.Direction.CCW);
        //向path中添加Circle
        path1.addCircle((float) (deltaX*2.5),deltaY/2,deltaY/2, Path.Direction.CCW);
        //向Path中添加Rect
        RectF rectF = new RectF(deltaX * 3, 0, deltaX * 4, deltaY);
        path1.addRect(rectF, Path.Direction.CCW);
        canvas.drawPath(path1,mPaint);


        /*--------------------------用Path画线--------------------------------*/
        mPaint.setStyle(Paint.Style.STROKE);//设置画笔为线条模式
        canvas.translate(0, deltaY * 2);
        Path path2 = path1;
        canvas.drawPath(path2, mPaint);



        /*-----------------使用lineTo、arcTo、quadTo、cubicTo画线--------------*/
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.translate(0,deltaY*3);
        Path path3 = new Path();
        //记录不同的path的各处连接点
        List<Point> pointList = new ArrayList<>();
        //1.第一部分，绘制线段
        path3.moveTo(0,0);
        path3.lineTo(deltaX/2,0); //绘制线段
        pointList.add(new Point(0,0));
        pointList.add(new Point(deltaX/2,0));

        //2. 第二部分，绘制椭圆右上角的四分之一的弧线
        RectF arcRecF1 = new RectF(0, 0, deltaX, deltaY);
        path3.arcTo(arcRecF1,270,90); //绘制圆弧
        pointList.add( new Point(deltaX,deltaY/2));

        //3. 第三部分，绘制椭圆左下角的四分之一的弧线
        //注意，我们此处调用了path的moveTo方法，将画笔的移动到我们下一处要绘制arc的起点上
        path3.moveTo(deltaX * 1.5f, deltaY);
        RectF arcRecF2 = new RectF(deltaX, 0, deltaX * 2, deltaY);
        path3.arcTo(arcRecF2, 90, 90);//绘制圆弧
        pointList.add(new Point((int)(deltaX * 1.5), deltaY));

        //4. 第四部分，绘制二阶贝塞尔曲线
        //二阶贝塞尔曲线的起点就是当前画笔的位置，然后需要添加一个控制点，以及一个终点
        //再次通过调用path的moveTo方法，移动画笔
        path3.moveTo(deltaX * 1.5f, deltaY);
        //绘制二阶贝塞尔曲线
        path3.quadTo(deltaX * 2, 0, deltaX * 2.5f, deltaY / 2);
        pointList.add(new Point((int)(deltaX * 2.5), deltaY / 2));

        //5. 第五部分，绘制三阶贝塞尔曲线，三阶贝塞尔曲线的起点也是当前画笔的位置
        //其需要两个控制点，即比二阶贝赛尔曲线多一个控制点，最后也需要一个终点
        //绘制三阶贝塞尔曲线
        path3.cubicTo(deltaX * 3, 0, deltaX * 3.5f, 0, deltaX * 4, deltaY);
        pointList.add(new Point(deltaX * 4, deltaY));

        canvas.drawPath(path3,mPaint);

        //把各个连接处的点画出来
        mPaint.setColor(Color.RED);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(10);
        for( Point point : pointList){
            canvas.drawPoint(point.x,point.y,mPaint);
        }


    }

    //画bitmap
    private void drawBitmap(Canvas canvas) {
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);

        //直接完全绘制Bitmap
        canvas.drawBitmap(bitmap, 0, 0, mPaint);

        //绘制Bitmap的一部分，并对其拉伸
        //srcRect定义了要绘制Bitmap的哪一部分
        //需要特别注意的是，srcRect中left、top、right、bottom的值都是以Bitmap本身的局部坐标系为基础的。
        Rect srcRect = new Rect();
        srcRect.left = 0;
        srcRect.right = bitmap.getWidth();
        srcRect.top = 0;
        srcRect.bottom = (int)(0.5 * bitmap.getHeight());
        float radio = (float)(srcRect.bottom - srcRect.top)  / bitmap.getWidth();
        //dstRecF定义了要将绘制的Bitmap拉伸到哪里
        RectF dstRecF = new RectF();
        dstRecF.left = 0;
        dstRecF.right = canvas.getWidth();
        dstRecF.top = bitmap.getHeight();
        float dstHeight = (dstRecF.right - dstRecF.left) * radio;
        dstRecF.bottom = dstRecF.top + dstHeight;
        canvas.drawBitmap(bitmap, srcRect, dstRecF, mPaint);
    }




}
